#include <lvgl.h>
#include <ESP32Video.h>
#include <GfxWrapper.h>
// -------------------------------
// Pin Configuration
// -------------------------------
const int redPin = 14;
const int greenPin = 19;
const int bluePin = 27;
const int hsyncPin = 32;
const int vsyncPin = 33;

// -------------------------------
// VGA Resolution (must match LVGL)
// -------------------------------
#define VGA_WIDTH 312
#define VGA_HEIGHT 235

// -------------------------------
// LVGL Draw Buffer
// -------------------------------
// Buffer size: 1/10th of screen (in pixels) * bytes per pixel
#define DRAW_BUF_SIZE (VGA_WIDTH * VGA_HEIGHT / 10)
static lv_color_t draw_buf[DRAW_BUF_SIZE];

// 定义BOOT按钮引脚
#define BOOT_BUTTON_PIN 0  // ESP32开发板上BOOT按钮通常连接到GPIO0

lv_obj_t *switch_obj;
// 全局变量：记录上一次按钮状态
int lastButtonState = HIGH;  // 假设未按下时为 HIGH（上拉）

// -------------------------------
// VGA Display Instance
// -------------------------------
VGA6Bit vga;
GfxWrapper<VGA6Bit> gfx(vga, 312, 235);

// -------------------------------
// LVGL Display Flush Callback
// This function sends the rendered frame to VGA
// -------------------------------
void my_disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
  int32_t w = lv_area_get_width(area);
  int32_t h = lv_area_get_height(area);

  // 针对RGB565格式（16位）解析颜色（与LV_COLOR_DEPTH 16匹配）
  for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
      uint32_t offset = y * w + x;
      // RGB565格式：2字节/像素（低字节蓝绿，高字节红绿）
      uint16_t color565 = *(uint16_t *)(px_map + offset * 2);

      // 提取RGB分量（简化为1位/通道，适配3位VGA）
      uint8_t r = (color565 >> 15) & 0x01;  // 取最高位红
      uint8_t g = (color565 >> 10) & 0x01;  // 取第10位绿
      uint8_t b = (color565 >> 4) & 0x01;   // 取第4位蓝

      // 转换为VGA可识别的颜色格式（保持RGB565直接输出更简单）
      gfx.drawPixel(area->x1 + x, area->y1 + y, color565);
    }
  }

  // Notify LVGL that flushing is done
  lv_display_flush_ready(disp);
}

// -------------------------------
// Optional: Touch input (if using touch)
// Here we use dummy for now
// -------------------------------
void my_touchpad_read(lv_indev_t *indev, lv_indev_data_t *data) {
  // No touch on VGA, so just return released state
  data->state = LV_INDEV_STATE_RELEASED;
}

// -------------------------------
// Tick Function (Arduino millis)
// -------------------------------
uint32_t my_tick_get(void) {
  return millis();
}

// -------------------------------
// Setup
// -------------------------------
void setup() {
  Serial.begin(115200);
  Serial.println("LVGL + VGA Demo");

  // Initialize VGA
  //设置分辨率，初始化vga
  Mode myMode = vga.MODE640x480.custom(312, 235);
  myMode.print<HardwareSerial>(Serial);
  vga.init(myMode, vga.VGABlackEdition);

  // Initialize LVGL
  lv_init();

  // Set tick source
  lv_tick_set_cb(my_tick_get);

  // Create display driver
  lv_display_t *display = lv_display_create(VGA_WIDTH, VGA_HEIGHT);
  lv_display_set_flush_cb(display, my_disp_flush);
  lv_display_set_buffers(display, draw_buf, NULL, sizeof(draw_buf), LV_DISPLAY_RENDER_MODE_PARTIAL);

  // Optional: Set rotation if needed
  // lv_display_set_rotation(display, LV_DISPLAY_ROTATION_0);

  // Create input device (optional, e.g., for buttons)
  // lv_indev_t *indev = lv_indev_create();
  // lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
  // lv_indev_set_read_cb(indev, my_touchpad_read);

  // -------------------------------
  // Create UI
  // -------------------------------

  // 1. 定义并初始化样式
  static lv_style_t label_style;
  lv_style_init(&label_style);

  // 2. 设置红色文本（使用十六进制）
  lv_style_set_text_color(&label_style, lv_color_hex(0xFF0000));

  lv_obj_t *label1 = lv_label_create(lv_screen_active());
  lv_label_set_text(label1, "Hello VGA LVGL!");
  // 应用样式到标签
  lv_obj_add_style(label1, &label_style, LV_PART_MAIN);
  lv_obj_align(label1, LV_ALIGN_CENTER, 0, -50);

  // 创建一个按钮
  lv_obj_t *btn = lv_btn_create(lv_screen_active());
  // 设置按钮位置（居中显示）
  lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0);
  // 设置按钮大小（可选，不设置则使用默认大小）
  lv_obj_set_size(btn, 70, 30);
  // 在按钮上添加文本标签
  lv_obj_t *label2 = lv_label_create(btn);
  lv_label_set_text(label2, "button");

  // 创建并初始化默认状态的样式
  static lv_style_t style_switch_bg_default;
  lv_style_init(&style_switch_bg_default);
  lv_style_set_bg_color(&style_switch_bg_default, lv_color_hex(0xFF0000));  // 红色背景

  // 创建并初始化选中状态的样式
  static lv_style_t style_switch_bg_checked;
  lv_style_init(&style_switch_bg_checked);
  lv_style_set_bg_color(&style_switch_bg_checked, lv_color_hex(0x87CEEB));  // 天蓝色背景

  // 创建一个开关
  switch_obj = lv_switch_create(lv_screen_active());
  lv_obj_align(switch_obj, LV_ALIGN_CENTER, 0, 50);
  lv_obj_set_size(switch_obj, 60, 30);
  lv_obj_add_state(switch_obj, LV_STATE_CHECKED);

  // 应用样式到开关的不同状态
  lv_obj_add_style(switch_obj, &style_switch_bg_default, LV_STATE_DEFAULT);  // 默认状态
  lv_obj_add_style(switch_obj, &style_switch_bg_checked, LV_STATE_CHECKED);  // 选中状态

  Serial.println("Setup complete. Running LVGL...");

  pinMode(BOOT_BUTTON_PIN, INPUT_PULLUP);  // 将BOOT按钮引脚设置为上拉输入模式
}

// -------------------------------
// Main Loop
// -------------------------------
void loop() {
  lv_timer_handler();  // Handle LVGL tasks
  delay(5);            // Small delay to avoid watchdog reset

  // 读取当前BOOT按钮状态
  int currentButtonState = digitalRead(BOOT_BUTTON_PIN);

  // 检测按钮从“松开”到“按下”的变化（下降沿），并做消抖
  if (lastButtonState == HIGH && currentButtonState == LOW) {
    // 检测到按下事件，延时消抖
    delay(20);  // 简单消抖，推荐用更精确的定时方式或非阻塞延时

    // 再次确认按钮是否仍处于按下状态（防止误触发）
    if (digitalRead(BOOT_BUTTON_PIN) == LOW) {
      Serial.println("BOOT button pressed (debounced)!");

      // 切换开关状态
      if (lv_obj_get_state(switch_obj) & LV_STATE_CHECKED) {
        lv_obj_clear_state(switch_obj, LV_STATE_CHECKED);
      } else {
        lv_obj_add_state(switch_obj, LV_STATE_CHECKED);
      }
    }
  }

  // 更新上一次按钮状态
  lastButtonState = currentButtonState;
}